/*
 * Project: 24ClockWidget
 * Copyright (C) 2009 rdrrlabs gmail com,
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.rdrrlabs.a24clock.prefs;

import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.os.Handler.Callback;
import android.preference.PreferenceActivity;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.RemoteViews;

import com.alfray.a24clock.R;
import com.rdrrlabs.a24clock.app.ClockApp;
import com.rdrrlabs.a24clock.app.ClockService;
import com.rdrrlabs.a24clock.error.ExceptionHandler;
import com.rdrrlabs.a24clock.error.ExceptionHandlerActivity;
import com.rdrrlabs.a24clock.stats.AgentWrapper;
import com.rdrrlabs.a24clock.stats.AgentWrapper.Event;
import com.rdrrlabs.a24clock.ui.IntroActivity;

/**
 * Activity to configure a new clock widget.
 * It's displayed when a new widget is created. The user must accept the
 * widget or it won't be dropped on home.
 * <p/>
 * Use {@link PrefsValues} to access the prefs later.
 */
public class WidgetPrefsUI extends PreferenceActivity {

    public static final String TAG = WidgetPrefsUI.class.getSimpleName();
    @SuppressWarnings("unused")
    private static final boolean DEBUG = true;
    private static final int MSG_REFRESH = 42;

    private ExceptionHandler mExceptionHandler;
    private int mWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
    private ClockApp mApp;
    private View mClockView;
    private PrefsValues mPrefValues;
    private Handler mHandler;
    private AgentWrapper mAgent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mExceptionHandler = new ExceptionHandler(this);
        super.onCreate(savedInstanceState);

        Intent intent = getIntent();
        Bundle extras = intent.getExtras();
        if (extras != null) {
            mWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
        }

        if (mWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
            Log.e(TAG, "Invalid/missing widget id");
            finish();
        }

        mApp = (ClockApp) getApplicationContext();
        mPrefValues = mApp.getPrefsValues(mWidgetId);

        setContentView(R.layout.widget_prefs);
        getPreferenceManager().setSharedPreferencesName(mPrefValues.getWidgetPrefsName());
        addPreferencesFromResource(R.xml.widget_prefs);
        setTitle("24 Clock - Widget Options");

        initDisplayClock();
        initButtons();
    }

    /** Same as {@link ExceptionHandlerActivity#onStart} */
    @Override
    protected void onStart() {
        if (mExceptionHandler == null) {
            mExceptionHandler = new ExceptionHandler(this);
        }
        super.onStart();

        mAgent = new AgentWrapper();
        mAgent.start(this);
        mAgent.event(Event.WidgetOptions);
    }

    /** Same as {@link ExceptionHandlerActivity#onStop} */
    @Override
    protected void onStop() {
        mAgent.stop(this);

        super.onStop();
        if (mExceptionHandler != null) {
            mExceptionHandler.detach();
            mExceptionHandler = null;
        }
    }

    @Override
    public void onResume() {
        super.onResume();

        // start the refresh only if in widget mode
        mHandler = new Handler(new RefreshCallback());
        mHandler.sendEmptyMessageDelayed(MSG_REFRESH, 900 /* ms */);
    }

    @Override
    public void onPause() {
        super.onPause();

        // Stop the refresh
        if (mHandler != null) {
            mHandler.removeMessages(MSG_REFRESH);
            mHandler = null;
        }
    }

    // ----------------

    private void initButtons() {
        Button b = (Button) findViewById(R.id.install);
        b.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                onAccept();
            }
        });

        b = (Button) findViewById(R.id.more2);
        if (b != null) {
            b.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    displayIntro();
                }
            });
        }
    }

    private void displayIntro() {
        Intent i = new Intent(this, IntroActivity.class);
        startActivityForResult(i, 0);
    }

    // ------------ Clock display ------------

    private void initDisplayClock() {
        ViewGroup clockRoot = (ViewGroup) findViewById(R.id.clock_root);

        if (clockRoot == null) return;

        try {
            RemoteViews rviews = mApp.configureRemoteView(
                    mWidgetId,
                    false /*enableTouch*/,
                    ClockApp.DIGITS_SIZE_2x1);
            mClockView = rviews.apply(this, clockRoot);
            clockRoot.addView(mClockView);

            mClockView.setClickable(false);
            mClockView.setFocusable(true);

            clockRoot.setClickable(true);
            clockRoot.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    Bundle extras = new Bundle(1);
                    extras.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID, mWidgetId);
                    mApp.triggerUserAction(extras);
                }
            });

        } catch (Exception e) {
            Log.d(TAG, "Inflate clock failed", e);
        }
    }

    private class RefreshCallback implements Callback {
        private long mMeanUpdateTime;

        @Override
        public boolean handleMessage(Message msg) {
            if (msg.what == MSG_REFRESH && mHandler != null) {

                long now = SystemClock.uptimeMillis();

                if (hasWindowFocus()) {
                    refreshClockDisplay();
                }

                // DEBUG
                long timeToUpdate = SystemClock.uptimeMillis() - now;

                if (mMeanUpdateTime == 0) {
                    mMeanUpdateTime = timeToUpdate;
                } else {
                    mMeanUpdateTime = (mMeanUpdateTime + timeToUpdate) / 2;
                }

                Log.d(TAG, String.format("Time to update: %d / %d",
                        timeToUpdate, mMeanUpdateTime));

                if (Long.MAX_VALUE - now > 1000) {
                    now += 1000;
                } else {
                    now = Long.MAX_VALUE;
                }
                mHandler.sendEmptyMessageAtTime(MSG_REFRESH, now);
            }
            return false;
        }
    }

    private void refreshClockDisplay() {
        if (mClockView != null) {
            try {
                RemoteViews rviews = mApp.configureRemoteView(
                        mWidgetId,
                        false /*enableTouch*/,
                        ClockApp.DIGITS_SIZE_2x1);
                rviews.reapply(this, mClockView);
            } catch (Exception e) {
                Log.d(TAG, "Inflate clock failed", e);
            }
        }
    }


    // ------------ Accept & finish ------------

    private void onAccept() {

        // stop the refresh
        if (mHandler != null) {
            mHandler.removeMessages(MSG_REFRESH);
            mHandler = null;
        }

        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);

        RemoteViews rviews = mApp.configureRemoteView(
                mWidgetId,
                true /*enableTouch*/,
                ClockApp.DIGITS_SIZE_2x1);
        appWidgetManager.updateAppWidget(mWidgetId, rviews);

        setConfigureResult(RESULT_OK);

        if (mAgent != null) {
            mAgent.event(Event.WidgetAdded);
        }

        // Easter egg. No longer here right.
        // Random rnd = new Random();
        // if (rnd.nextFloat() < .3) {  // 30% chance to get the effect
        //     mApp.playSound(R.raw.easter, 1);
        // }

        finish();
    }

    /**
     * Sets the result of this activity, with the correct widget id
     * using {@link #mWidgetId}.
     *
     * @param resultCode One of {@link Activity#RESULT_OK} or
     *          {@link Activity#RESULT_CANCELED}
     */
    private void setConfigureResult(int resultCode) {
        Intent resultValue = new Intent();
        resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mWidgetId);
        setResult(resultCode, resultValue);
        ClockService.clearCachedIds();
    }

}
